// 7.运算符
// 7.1.算术运算符
// 7.1.1.加法运算符
let sum = 5 + 3;  // 8
let strSum = "Hello" + " " + "World";  // "Hello World" (字符串连接)

// 7.1.2.减法运算符
let difference = 10 - 4;  // 6
let negative = 5 - 8;     // -3

// 7.1.3.乘法运算符
let product = 6 * 7;  // 42

// 7.1.4.除法运算符
let quotient = 20 / 5;  // 4
let decimal = 5 / 2;    // 2.5

// 7.1.5.求余运算符
let remainder = 10 % 3;  // 1 (因为10除以3得3余1)
let evenCheck = 8 % 2;   // 0 (偶数)
let oddCheck = 7 % 2;    // 1 (奇数)
// 7.1.6.求幂运算符
let power = 2 ** 3;  // 8 (2的3次方)
let square = 3 ** 2; // 9

// 7.1.6.自增运算符
let x = 5;
x++;  // x现在是6 (后置递增)
++x;  // x现在是7 (前置递增)

// 7.1.7.自减运算符
let y = 10;
y--;  // y现在是9 (后置递减)
--y;  // y现在是8 (前置递减)


// 赋值运算符与算数运算符的组合
let a = 10;

a += 5;  // 等同于 a = a + 5; 现在a是15
a -= 3;  // 等同于 a = a - 3; 现在a是12
a *= 2;  // 等同于 a = a * 2; 现在a是24
a /= 4;  // 等同于 a = a / 4; 现在a是6
a %= 4;  // 等同于 a = a % 4; 现在a是2
a **= 3; // 等同于 a = a ** 3; 现在a是8


// 关系运算符
/*
 * JavaScript关系运算符用于比较两个值，返回布尔值(true/false)
 * 以下是所有关系运算符的详细说明和示例
 */

// 1. 大于(>): 检查左值是否大于右值
console.log(5 > 3);   // true (5大于3)
console.log(3 > 5);   // false (3不大于5)
console.log(5 > 5);   // false (5不大于5)

// 2. 小于(<): 检查左值是否小于右值
console.log(3 < 5);   // true (3小于5)
console.log(5 < 3);   // false (5不小于3)
console.log(5 < 5);   // false (5不小于5)

// 3. 大于等于(>=): 检查左值是否大于或等于右值
console.log(5 >= 3);  // true (5大于3)
console.log(3 >= 5);  // false (3不大于等于5)
console.log(5 >= 5);  // true (5等于5)

// 4. 小于等于(<=): 检查左值是否小于或等于右值
console.log(3 <= 5);  // true (3小于5)
console.log(5 <= 3);  // false (5不小于等于3)
console.log(5 <= 5);  // true (5等于5)

// 5. 相等(==): 宽松相等，会进行类型转换
console.log(5 == 5);     // true (相同值)
console.log(5 == '5');   // true (字符串'5'转换为数字5)
console.log(true == 1);  // true (true转换为1)
console.log(false == 0); // true (false转换为0)
console.log(null == undefined); // true (特殊规则)

// 6. 不等(!=): 宽松不等，会进行类型转换
console.log(5 != 3);     // true (5不等于3)
console.log(5 != '5');   // false (类型转换后相等)
console.log(true != 1);  // false (类型转换后相等)

// 7. 严格相等(===): 比较值和类型，不进行类型转换
console.log(5 === 5);     // true (相同值和类型)
console.log(5 === '5');   // false (相同值但类型不同)
console.log(true === 1);  // false (不同类型)
console.log(null === undefined); // false (不同类型)

// 8. 严格不等(!==): 比较值或类型，不进行类型转换
console.log(5 !== 3);     // true (值不同)
console.log(5 !== '5');   // true (类型不同)
console.log(true !== 1);  // true (类型不同)

/*
 * 特殊比较情况说明
 */

// NaN比较: NaN与任何值(包括自己)都不相等
console.log(NaN == NaN);   // false
console.log(NaN === NaN);  // false
console.log(isNaN(NaN));   // true (使用isNaN函数检测)

// 对象比较: 比较的是引用而非内容
let obj1 = {a: 1};
let obj2 = {a: 1};
let obj3 = obj1;
console.log(obj1 == obj2);  // false (不同对象引用)
console.log(obj1 === obj2); // false
console.log(obj1 == obj3);  // true (相同对象引用)

// 字符串比较: 按字典序(Unicode码点)比较
console.log('a' < 'b');     // true ('a'的Unicode码点小于'b')
console.log('apple' < 'banana'); // true (逐个字符比较)
console.log('10' < '2');    // true (字符串'1'的码点小于'2')
console.log('10' < 2);      // false (字符串'10'转换为数字10)

/*
 * 最佳实践建议
 * 1. 大多数情况下使用===和!==代替==和!=
 * 2. 比较前确保类型一致，避免意外类型转换
 * 3. 对于浮点数比较，考虑精度问题
 */

// 7.2.逻辑运算符
/*
 * JavaScript逻辑运算符用于将布尔值组合在一起
 * 以下是所有逻辑运算符的详细说明和示例
 */
// 1. 逻辑非(!): 将布尔值取反
// // 任何值取反为布尔值
console.log(!true);  // false
console.log(!false); // true
console.log(!5);     // false (非零值取反为false)
console.log(!0);     // true (零值取反为true)
console.log(!'');    // true (空字符串取反为true)
console.log(!'hello'); // false (非空字符串取反为false)
console.log(!null);  // true (null取反为true)
console.log(!undefined); // true (undefined取反为true)
console.log(!{});    // false (非空对象取反为false)
console.log(![]);    // false (空数组取反为false)
console.log(!NaN);   // true (NaN取反为true)
console.log(!Infinity); // false (Infinity取反为false)
console.log(!function(){}); // false (非空函数取反为false)
console.log(!/hello/); // false (非空正则表达式取反为false)
console.log(!new Date()); // false (非空日期对象取反为false)
console.log(!new Error()); // false (非空错误对象取反为false)
// console.log(!document); // false (非空文档对象取反为false)
// console.log(!window); // false (非空窗口对象取反为false)
// console.log(!document.all); // false (非空document.all取反为false)
// console.log(!document.all[0]); // false (非空document.all[0]取反为false)





// 2. 逻辑与(&&): 如果第一个值是false，则返回第一个值，否则返回第二个值
// 从左往右进行计算 遇假就返回该表达式结果，一直没遇假， 则返回最后一个值
console.log(true && true);  // true
console.log(true && false); // false







// 3. 逻辑或(||): 如果第一个值是true，则返回第一个值，否则返回第二个值
// 从左往右进行计算 遇真就返回该表达式结果，一直没遇真， 则返回最后一个值
console.log(true || true);  // true
console.log(true || false); // true
console.log(true || false); // true
console.log(false || false); // false




// 4. 逻辑异或(^): 如果两个值有且只有一个为true，则返回true，否则返回false
console.log(true ^ true);  // false
console.log(true ^ false); // true
console.log(false ^ true); // true
console.log(false ^ false); // false





// 5. 逻辑与或(||和&&): 优先级高于逻辑异或(^)
console.log(true || true && false); // true
console.log(true || (true && false)); // true
console.log((true || true) && false); // false
console.log(true || true && false); // true
console.log(true || true && false); // true
console.log(true || (true && false)); // true
console.log((true || true) && false); // false
console.log(true || true && false); // true
console.log(true || true && false); // true
console.log(true || true && false); // true
console.log(true || true && false); // true
console.log(true || true && false); // true
console.log(true || true && false); // true
console.log(true || true && false); // true


// 7.3.条件运算符
/*
 * 条件运算符(也称为三元运算符)是唯一一个需要三个操作数的运算符
 * 语法: condition ? value1 : value2
 * 如果condition为true，则返回value1，否则返回value2
 */
// 1. 三元运算符
let age = 18;
let message = age >= 18 ? 'adult' : 'teenager';
// 如果age >= 18，message为'adult'，否则为'teenager'
console.log(message); // teenager


// 位运算符
/*
 * 位运算符用于处理整数的二进制位
 * 以下是所有位运算符的详细说明和示例
 */
// 1. 按位非(~): 对数值的每个二进制位取反
// 任何值按位取反的结果都是一个负数
console.log(~5); // -6
console.log(~-5); // 4
console.log(~5);

// 隐式类型转换
